// Maciej Chałapuk (maciej@chalapuk.pl)
// vim: ts=2 sw=2 expandtab
#include "bitset.hpp"

#include <boost/test/unit_test.hpp>
#include <cinttypes>
#include <iostream>

BOOST_AUTO_TEST_SUITE( bitset )


BOOST_AUTO_TEST_CASE( copy ) {
  const size_t size = 8 * sizeof(intptr_t);
  experiment::bitset<size> bitset;
  experiment::bitset<size> copy = bitset;
  for (size_t i = 0; i < size; ++i) {
    BOOST_CHECK_EQUAL(copy[i], bitset[i]);
  }   
}

BOOST_AUTO_TEST_CASE( reset ) {
  const size_t size = 8 * sizeof(intptr_t);
  experiment::bitset<size> bitset;
  bitset.reset();
  for (size_t i = 0; i < size; ++i) {
    BOOST_CHECK_EQUAL(false, bitset[i]);
  }   
}

BOOST_AUTO_TEST_CASE( flip ) {
  const size_t size = 8 * sizeof(intptr_t);
  experiment::bitset<size> bitset;
  bitset.reset();
  bitset.flip();
  for (size_t i = 0; i < size; ++i) {
    BOOST_CHECK_EQUAL(true, bitset[i]);
  }   
}

BOOST_AUTO_TEST_CASE( count ) {
  const size_t size = 8 * sizeof(intptr_t);
  experiment::bitset<size> bitset;
  bitset.reset();
  bitset[0] = true;
  BOOST_CHECK_EQUAL(bitset.count(), 1);
  bitset.flip();
  BOOST_CHECK_EQUAL(bitset.count(), size-1);
}

BOOST_AUTO_TEST_CASE( assign ) {
  const size_t size = 2 * 8 * sizeof(intptr_t);
  experiment::bitset<size> bitset;
  for (size_t i = 0; i < size; ++i) {
    bitset[i] = true;
    BOOST_CHECK_EQUAL(true, bitset[i]);
    bitset[i] = false;
    BOOST_CHECK_EQUAL(false, bitset[i]);
  }
}

bool mask(size_t num, size_t pos) {
  static const size_t one = 1;
  return static_cast<bool>(num & (one << pos));
}

BOOST_AUTO_TEST_CASE( assign2 ) {
  const size_t size = 2 * 8 * sizeof(intptr_t);
  const size_t half = size/2;
  const size_t max = std::numeric_limits<size_t>::max();
  for (size_t num = max-10000; num < max; num+=1000) {
    experiment::bitset<size> bitset;
    bitset.reset();
    for (size_t i = 0; i < half; ++i) {
      bitset[i] = mask(num, i);
    }
    for (size_t i = half; i > 0; --i) {
      bitset[size-i] = mask(num, i);
    }
    for (size_t i = 0; i < half; ++i) {
      BOOST_CHECK_EQUAL(mask(num, i), bitset[i]);
    }
    for (size_t i = half; i > 0; --i) {
      BOOST_CHECK_EQUAL(mask(num, i), bitset[size-i]);
    }
  }
}

BOOST_AUTO_TEST_CASE( bitwise_and ) {
  const size_t size = 16 * 8 * sizeof(intptr_t);
  experiment::bitset<size> bitset1;
  experiment::bitset<size> bitset2;

  bitset1.reset();
  bitset2.reset();
  bitset2.flip();
  bitset1 &= bitset2;
  for (size_t i = 0; i < size; ++i) {
    BOOST_CHECK_EQUAL(false, bitset1[i]);
  }

  bitset1[0] = true;
  bitset2 &= bitset1;
  BOOST_CHECK_EQUAL(true, bitset2[0]);
  for (size_t i = 1; i < size; ++i) {
    BOOST_CHECK_EQUAL(false, bitset2[i]);
  }

  bitset2[size-1] = true;
  bitset1.reset();
  bitset1.flip();
  bitset1 &= bitset2;
  BOOST_CHECK_EQUAL(true, bitset1[0]);
  BOOST_CHECK_EQUAL(true, bitset1[size-1]);
  for (size_t i = 1; i < size-1; ++i) {
    BOOST_CHECK_EQUAL(false, bitset1[i]);
  }
}


BOOST_AUTO_TEST_SUITE_END()

